home *** CD-ROM | disk | FTP | other *** search
- /* game.c */
-
- /* Adapted for the DJGPP ALLEGRO game package */
- /* Seymour Shlien 24-Aug-97 */
-
- /* This file contains the code for moving */
- /* the explorer on the board and interating */
- /* with the falling blocks, monsters, ... */
-
- /* Besides the elimination of all the calls to curses/termcap */
- /* and replacement with new functions in the display.c file, */
- /* there were a few other changes made to the user interface. */
- /* The #,~,?,q,m,n,<,> commands in the older version have been */
- /* replaced with Function key commands and the F6 menu. Though */
- /* R, S and cntl-R and cntl-W are still there, they are not */
- /* supported commands. Hopefully, the player does not press */
- /* these keys accidentally. cntl-L for loading the solution */
- /* from a designated file if it exists is a new command */
- /* described in the help.txt file. I didn't put it in the menu */
- /* because I don't want everybody to know about it. */
-
- /* Another significant change, is that the game either runs */
- /* in record mode or playback. I got rid of all the checkpoint */
- /* stuff +,-,& in the record/playback mode. Everything is now */
- /* automatic and transparent to the user who does not have to */
- /* remember to turn the recorder on or off as in wandr330.zip */
-
-
- #include "wand_head.h"
- #include <allegro.h>
- #include "samples.h"
-
- /* I do not install_keyboard() but use the regular bios keyboard */
- /* driver. Except for cntl keys, users do not press two keys at once.*/
- /* This makes debugging using Rhide1.3 a little easier. */
-
- #define UP_ARROW 328
- #define DOWN_ARROW 336
- #define LEFT_ARROW 331
- #define RIGHT_ARROW 333
-
-
- int playback_flag; /* indicates whether F5 key is active */
- extern int audio_flag; /* switches audio on or off */
- extern int midi_flag; /* switches midi on or off */
-
- extern int move_monsters();
- extern int check();
- extern void display();
- extern int fall();
- extern void map();
- extern void redraw_screen();
- extern struct mon_rec *make_monster();
-
-
- /* This array contains the representation of the game/puzzle.
- It is read in from one of the level files and the array
- maintains the state of the game.
- */
- extern char lscreen[NOOFROWS][ROWLEN+1];
-
-
- extern int debug_disp; /* switches between map and zoom mode */
- extern char *edit_memory; /* memory for all key strokes, the amount */
- extern char *memory_end; /* of space is set by EMSIZE in wand_hea.h */
- extern int pause2; /* for slowing playback and animation */
- extern int pause1;
- extern int gamelevel; /* The new level the user wants to go to */
- extern int recording; /* Flag 1,2 for record and playback */
- extern int signal_reload; /* from display.c indicates that level */
- /* reload is necessary. */
-
- struct mon_rec start_of_list = {0,0,0,0,0,NULL,NULL};
- struct mon_rec *last_of_list, *tail_of_list;
-
- int nx,ny; /* we need it global to allow for scrolling */
-
- /* Actual game function - Calls fall() to move boulders and arrows
- recursively.
- Variable explanation :
- x,y : where you are
- nx,ny : where you're trying to move to
- sx,sy : where the screen window on the playing area is
- mx,my : where the monster is
- tx,ty : teleport arrival
- bx,by : baby monster position
- nbx,nby : where it wants to be
- lx,ly : the place you left when teleporting
- nf : how many diamonds you've got so far
- new_disp : the vector the baby monster is trying
- */
- extern int old_score; /* save old score in case of retry or killed */
-
-
-
-
- char *playscreen(num, score, maxmoves, keys)
- int *num, maxmoves;
- long *score;
- char keys[10];
- {
- int x, y, deadyet = 0, sx = -1, sy = -1, tx = -1, ty = -1,
- lx = 0, ly = 0, mx = -1, my = -1,
- diamonds = 0, nf = 0, tmpx, tmpy;
- char (*frow)[ROWLEN+1] = lscreen, buffer[25];
- int ch;
- struct mon_rec *monster;
- static char howdead[25];
- char *memory_ptr;
- int ier;
- int pathsize;
- int signal_teleport; /* indicates teleport occurred (for zoom mode) */
- char comment[60];
-
- old_score = *score;
- tail_of_list = &start_of_list;
- memory_ptr = edit_memory;
-
-
-
- /* Scan the screen and find the explorer, monsters and count the*/
- /* number of diamonds. Replace teleport arrival with blank. */
-
- for (x = 0; x <= ROWLEN; x++)
- for (y = 0; y < NOOFROWS; y++) {
- if ((lscreen[y][x] == '*') || (lscreen[y][x] == '+'))
- diamonds++;
- if (lscreen[y][x] == 'A') { /* note teleport arrival point & */
- /* replace with space */
- tx = x;
- ty = y;
- lscreen[y][x] = ' ';
- }
- if (lscreen[y][x] == '@') {
- sx = x;
- sy = y;
- }
- if (lscreen[y][x] == 'M') { /* Put megamonster in */
- mx = x;
- my = y;
- }
- if (lscreen[y][x] == 'S') { /* link small monster to pointer chain */
- if ((monster = make_monster(x,y)) == NULL) {
- strcpy(howdead,"running out of memory");
- return howdead;
- }
- if (!viable(x,y-1)) { /* make sure its running in the */
- /* correct direction.. */
- monster->mx = 1;
- monster->my = 0;
- } else if (!viable(x+1,y)) {
- monster->mx = 0;
- monster->my = 1;
- } else if (!viable(x,y+1)) {
- monster->mx = -1;
- monster->my = 0;
- } else if (!viable(x-1,y)) {
- monster->mx = 0;
- monster->my = -1;
- }
- }
- if (lscreen[y][x] == '-')
- lscreen[y][x] = ' ';
- }
- x = sx;
- y = sy;
- if ((x == -1) && (y == -1)) { /* no start position in screen ? */
- strcpy(howdead,"a screen design error");
- return(howdead);
- }
-
- if (maxmoves < 1) maxmoves = -1;
-
-
-
-
-
- update_game: /* restored game restarts here */
-
- redraw_screen(maxmoves,*num,*score,nf,diamonds,mx,sx,sy,frow);
- nx = x;
- ny = y;
- signal_teleport =0;
-
-
- /* THE GAME STARTS HERE. */
-
- while (deadyet == 0) {
- refresh_screen();
- switch (recording) {
-
- case 1: /* Recording */
- ch = getkey();
- while (kbhit()) getch(); /* clear keyboard buffer */
-
- /* convert arrow keys to movement keys if necessary*/
- if (ch == LEFT_ARROW) ch = keys[2];
- else if (ch == RIGHT_ARROW) ch = keys[3];
- else if (ch == UP_ARROW) ch= keys[0];
- else if (ch == DOWN_ARROW) ch = keys[1];
-
- if((ch == keys[0]) || (ch == keys[1]) || (ch == keys[2]) ||
- (ch == keys[3]))
- { *memory_ptr++ = ch;
- maxmoves--;
- memory_end++;
- if(playback_flag == 1)
- {
- playback_flag =0;
- make_control_bar();
- }
- }
- else if(ch>31 && ch<128 && ch != 'R' && ch != 'S')
- { /* if not control or function key */
- *memory_ptr++ = ' '; /* non movement keys represented */
- memory_end++; /* by space. monsters can move*/
- if(playback_flag == 1)
- {
- playback_flag =0;
- make_control_bar();
- }
- }
- if(maxmoves > 0) notify_maxmoves(maxmoves);
- break;
-
-
- case 2: /* Playback */
- if (bioskey(1)) /* check for interrupt */
- { /* and stop playback if*/
- recording = 1; /* present. */
- continue;
- }
-
- ch = *memory_ptr;
- memory_ptr++;
- delay(pause2); /* slow it down */
- if(ch != ' ') maxmoves--;
- if (ch == '\0')
- ch = ')';
- break;
- default:
- alert_message("program error: recording not 1 or 2");
-
- }
-
-
-
- nx = x;
- ny = y;
-
- /************************************************************/
- /* Execute movement keys */
- /************************************************************/
-
- if ((ch == keys[3]) && (x <(ROWLEN-1)))
- nx++;
- if ((ch == keys[2]) && (x > 0))
- nx--;
- if ((ch == keys[1]) && (y <(NOOFROWS-1)))
- ny++;
- if ((ch == keys[0]) && (y > 0))
- ny--;
-
- if (ch == 315) { /* F1. Help key */
- show_help();
- continue; /* don't move monsters */
- }
-
-
- if (ch == 316) { /* F2. About window */
- draw_about_window();
- continue; /* don't move monsters */
- }
-
- /**************************************************************/
- /* Quit, Restart */
- /**************************************************************/
-
-
- if (ch == 318) { /* F4. restart same level */
- if(memory_ptr != edit_memory) /* in case you press F4 twice */
- {
- playback_flag = 1;
- *memory_ptr = ')';
- }
- *score = old_score;
- sprintf(howdead,"~%c",*num);
- return howdead;
- }
-
- if (ch == 27) { /* ESC. */
- strcpy(howdead,"quitting the game");
- return howdead;
- }
-
- /**************************************************************/
- /* Display Options */
- /**************************************************************/
-
-
- if (ch == 317) { /* F3 */
- debug_disp = 1 - debug_disp;
- if(debug_disp) clear_remnant();
- continue;
- }
-
-
- /**************************************************************/
- /* Memory Functions */
- /**************************************************************/
-
-
- if (ch == ')')
- {
- if (recording == 2)
- {
- recording = 1;
- memory_ptr--;
- memory_end = memory_ptr;
- }
- continue; /* don't move monsters if present */
- }
-
- if (ch == 319) /* F5 */
- {
- if (playback_flag)
- { /* playback memory */
- recording = 2;
- playback_flag =0;
- make_control_bar();
- }
- continue;
- }
-
-
- if (ch == 320) /* F6 */
- {
- menu_interface();
- if(signal_reload)
- {
- sprintf(howdead,"~%c",gamelevel);
- if(midi_flag) load_and_play_midi();
- return howdead;
- }
- continue;
- }
-
-
-
-
-
- /**************************************************************/
- /* Save, Restore options */
- /**************************************************************/
-
- /* Added save/restore game feature. Gregory H. Margo */
-
- if (ch == 'S') { /* save game */
- extern struct save_vars zz;
-
- /* stuff away important local variables to be saved */
- /* so the game state may be acurately restored */
- zz.z_x = x;
- zz.z_y = y;
- zz.z_sx = sx;
- zz.z_sy = sy;
- zz.z_tx = tx;
- zz.z_ty = ty;
- zz.z_mx = mx;
- zz.z_my = my;
- zz.z_diamonds = diamonds;
- zz.z_nf = nf;
-
- save_game(*num, score, audio_flag, maxmoves);
- /* NOTREACHED ... unless there's been an error. */
- }
-
- if (ch == 'R') { /* restore game */
- extern struct save_vars zz;
-
- ier = restore_game(num, score, audio_flag, &maxmoves);
-
- if(ier == 0)
- {
- /* recover important local variables */
- x = zz.z_x;
- y = zz.z_y;
- sx = zz.z_sx;
- sy = zz.z_sy;
- tx = zz.z_tx;
- ty = zz.z_ty;
- mx = zz.z_mx;
- my = zz.z_my;
- diamonds = zz.z_diamonds;
- nf = zz.z_nf;
- }
-
- goto update_game; /* the dreaded goto */
- }
-
-
- if (ch == 12) /* ctrl l -- read solution data */
- {
- if(memory_ptr != edit_memory)
- {
- alert_message("First press F4 to restart");
- continue;
- }
-
- ier = edit_restore(*num);
- if(ier >= 0) playback_flag=1;
- make_control_bar();
- continue; /* do not move monsters if present */
- }
-
- if (ch == 18) /* ctrl r -- read memory data */
- {ier = edit_restore(0);
- if(ier >= 0) playback_flag=1;
- make_control_bar();
- continue; /* do not move monsters if present */
- }
-
- if (ch == 23) /* ctrl w -- write memory data */
- {edit_save(-1);
- continue;
- }
-
- if (lscreen[ny][nx] == 'C') {
- lscreen[ny][nx] = ':';
- *score+=4;
- if(audio_flag) play_audio_sample(GET_CAPSULE_SND);
- if (maxmoves != -1)
- maxmoves+=250;
- }
-
-
- /**************************************************************/
- /* G A M E A C T I O N S */
- /**************************************************************/
-
-
-
- switch (lscreen[ny][nx]) {
- case '@': break;
- case '*': *score+=9;
- nf++;
- notify_diamonds(nf,diamonds);
- if(audio_flag) play_audio_sample(GET_DIAMOND_SND);
- case ':': *score+=1;
- notify_score(*score);
- case ' ':
- lscreen[y][x] = ' ';
- lscreen[ny][nx] = '@';
- draw_object(y,x,' ');
- draw_object(ny,nx,'@');
- deadyet += check(&mx,&my,x,y,nx-x,ny-y,sx,sy,howdead);
- y = ny;
- x = nx;
- break;
- case 'O':
- if ((nx == 0) || (nx == ROWLEN)) break;
- if (lscreen[y][nx*2-x] == 'M') {
- lscreen[y][nx*2-x] = ' ';
- mx = my = -1;
- *score+=100;
- notify_score(*score);
- }
- if (lscreen[y][nx*2-x] == ' ') {
- lscreen[y][nx*2-x] = 'O';
- lscreen[y][x] = ' ';
- lscreen[ny][nx] = '@';
- draw_object(y,x,' ');
- draw_object(ny,nx,'@');
- draw_object(y,nx*2-x,'O');
- deadyet += fall(&mx,&my,nx*2-x,y+1,sx,sy,howdead);
- deadyet += fall(&mx,&my,x*2-nx,y,sx,sy,howdead);
- deadyet += fall(&mx,&my,x,y,sx,sy,howdead);
- deadyet += fall(&mx,&my,x,y-1,sx,sy,howdead);
- deadyet += fall(&mx,&my,x,y+1,sx,sy,howdead);
- y = ny;
- x = nx;
- }
- break;
- case '^':
- if ((nx == 0) || (nx == ROWLEN)) break;
- if (lscreen[y][nx*2-x] == ' ') {
- lscreen[y][nx*2-x] = '^';
- lscreen[y][x] = ' ';
- lscreen[ny][nx] = '@';
- draw_object(y,x,' ');
- draw_object(ny,nx,'@');
- draw_object(y,nx*2-x,'^');
- deadyet += fall(&mx,&my,nx*2-x,y-1,sx,sy,howdead);
- deadyet += fall(&mx,&my,x*2-nx,y,sx,sy,howdead);
- deadyet += fall(&mx,&my,x,y,sx,sy,howdead);
- deadyet += fall(&mx,&my,x,y+1,sx,sy,howdead);
- deadyet += fall(&mx,&my,x,y-1,sx,sy,howdead);
- y = ny;
- x = nx;
- }
- break;
- case '<':
- case '>':
- if ((ny == 0) || (ny == NOOFROWS)) break;
- if (lscreen[ny*2-y][x] == 'M') {
- lscreen[ny*2-y][x] = ' ';
- mx = my = -1;
- *score+=100;
- notify_score(*score);
- }
- if (lscreen[ny*2-y][x] == ' ') {
- lscreen[ny*2-y][x] = lscreen[ny][nx];
- lscreen[y][x] = ' ';
- lscreen[ny][nx] = '@';
- draw_object(y,x,' ');
- draw_object(ny,nx,'@');
- draw_object(ny*2-y,x,lscreen[ny*2-y][x]);
- deadyet += fall(&mx,&my,x,y,sx,sy,howdead);
- deadyet += fall(&mx,&my,x-1,(ny>y)?y:(y-1)
- ,sx,sy,howdead);
- deadyet += fall(&mx,&my,x+1,(ny>y)?y:(y-1)
- ,sx,sy,howdead);
- deadyet += fall(&mx,&my,x-1,ny*2-y,sx,sy,howdead);
- deadyet += fall(&mx,&my,x+1,ny*2-y,sx,sy,howdead);
- y = ny;
- x = nx;
- }
- break;
- case '~':
- if (((2*nx-x) < 0) || ((ny*2-y) > NOOFROWS) || ((ny*2-y) < 0) ||
- ((2*nx-x) > ROWLEN)) break;
- if (lscreen[ny*2-y][nx*2 -x] == 'M') {
- lscreen[ny*2-y][nx*2-x] = ' ';
- mx = my = -1;
- *score+=100;
- notify_score(*score);
- }
- if (lscreen[ny*2-y][nx*2-x] == ' ') {
- lscreen[ny*2-y][nx*2-x] = '~';
- lscreen[y][x] = ' ';
- lscreen[ny][nx] = '@';
- draw_object(y,x,' ');
- draw_object(ny,nx,'@');
- draw_object(ny*2-y,nx*2-x,'~');
- deadyet += check(&mx,&my,x,y,nx-x,ny-y,sx,sy,howdead);
- y = ny; x = nx;
- }
- break;
- case '!':
- strcpy(howdead,"an exploding landmine");
- deadyet = 1;
- draw_object(y,x,' ');
- draw_object(ny,nx,'@');
- if(audio_flag) play_audio_sample(KILLED_BY_MINE_SND);
- break;
- case 'X':
- if (nf == diamonds) {
- *score+=250;
- recording=1;
- playback_flag=0;
- pathsize = size_of_path_file(*num);
- if(recording == 1)
- {
- memory_ptr -= 2;
- *memory_ptr = ')';
- if(audio_flag) play_audio_sample(LEVEL_DONE_SND);
- if(pathsize == 0)
- {
- edit_save(*num);
- alert_congratulations(0);
- }
- else if ((pathsize - 5) > (memory_ptr - edit_memory))
- {
- edit_save(*num);
- alert_congratulations(1);
- }
- }
- gamelevel = (*num) + 1;
- if(midi_flag) load_and_play_midi();
- return NULL;
- }
- break;
- case 'T':
- if (tx > -1) {
- lscreen[ny][nx] = ' ';
- lscreen[y][x] = ' ';
- lx = x;
- ly = y;
- y = ty;
- x = tx;
- lscreen[y][x] = '@';
- sx = x;
- sy = y;
- *score += 20;
- notify_score(*score);
- map(frow);
- signal_teleport =1;
- deadyet += fall(&mx,&my,nx,ny,sx,sy,howdead);
- if (deadyet == 0)
- deadyet = fall(&mx,&my,lx,ly,sx,sy,howdead);
- if (deadyet == 0)
- deadyet = fall(&mx,&my,lx+1,ly-1,sx,sy,howdead);
- if (deadyet == 0)
- deadyet = fall(&mx,&my,lx+1,ly+1,sx,sy,howdead);
- if (deadyet == 0)
- deadyet = fall(&mx,&my,lx-1,ly+1,sx,sy,howdead);
- if (deadyet == 0)
- deadyet = fall(&mx,&my,lx-1,ly-1,sx,sy,howdead);
- } else {
- lscreen[ny][nx] = ' ';
- printf("Teleport out of order");
- }
- break;
- case 'M':
- strcpy(howdead,"a hungry monster");
- deadyet = 1;
- draw_object(y,x,' ');
- if(audio_flag) play_audio_sample(KILLED_BY_M_SND);
- break;
- case 'S':
- strcpy(howdead,"walking into a monster");
- deadyet = 1;
- draw_object(y,x,' ');
- if(audio_flag) play_audio_sample(KILLED_BY_S_SND);
- break;
- default:
- break;
- }
-
-
-
-
-
- if ((y == ny) && (x == nx) && (maxmoves > 0))
- notify_maxmoves(maxmoves);
-
- if (maxmoves == 0) {
- strcpy(howdead,"running out of moves");
- if(audio_flag) play_audio_sample(NO_MOVES_SND);
- deadyet = 1;
- }
-
- if (signal_teleport)
- {
- /* we have to update nx,ny here so the zoom screen */
- /* scrolls the right location. */
- nx = x;
- ny = y;
- draw_object(ny,nx,'@'); /* initiates the scrolling */
- if(audio_flag) play_audio_sample(TELEPORT_SND);
- signal_teleport = 0;
- }
-
- deadyet += move_monsters(&mx,&my,score,howdead,sx,sy
- ,nf,x,y,diamonds);
-
-
- }
- if(recording==1)
- *(memory_ptr-2) = ')'; /* step back to avoid death */
- playback_flag=1;
- return(howdead);
- }
-